﻿#ifndef OSGQT_H
#define OSGQT_H

#include <osgViewer/GraphicsWindow>
#include <OpenThreads/ReadWriteMutex>
#include <osg/ArgumentParser>
#include <osg/MatrixTransform>
#include <osg/ShapeDrawable>
#include <osg/Depth>

#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QReadWriteLock>


#include <osgViewer/Viewer>

class QInputEvent;
class QKeyEvent;
class QMouseEvent;
class QWheelEvent;

namespace osgViewer
{
class Viewer;
}
namespace eveBIM
{
class ViewerWidget;
}

class HUDAxis:public osg::Camera
{
public:
    HUDAxis();
    HUDAxis(HUDAxis const& copy, osg::CopyOp copyOp = osg::CopyOp::SHALLOW_COPY);
    META_Node(osg, HUDAxis);
    inline void setMainCamera(Camera* camera){ _mainCamera = camera;}
    virtual void traverse(osg::NodeVisitor& nv);
protected:
    virtual ~HUDAxis();
    osg::observer_ptr<osg::Camera> _mainCamera;
};

class OSGRenderer : public QObject, public osgViewer::Viewer
{
    bool                                       m_osgInitialized {false};
    osg::ref_ptr<osgViewer::GraphicsWindow>    m_osgWinEmb;
    float                                      m_windowScale {1.0f};
    bool                                       m_continuousUpdate {true};

    int                                        _timerId{0};
    osg::Timer                                 _lastFrameStartTime;
    bool                                       _applicationAboutToQuit {false};
    bool                                       _osgWantsToRenderFrame{true};
    osg::MatrixTransform* viewMatrix;
    osg::ref_ptr<osg::Group> root;
    osg::ref_ptr<HUDAxis> HUDroot;

    Q_OBJECT

    //friend class eveBIM::ViewerWidget;

public:

    explicit OSGRenderer(QObject* parent = nullptr);
    explicit OSGRenderer(osg::ArgumentParser* arguments, QObject* parent = nullptr);

    ~OSGRenderer() override;

    bool continuousUpdate() const
    {
        return m_continuousUpdate;
    }
    void setContinuousUpdate(bool continuousUpdate)
    {
        m_continuousUpdate = continuousUpdate;
    }
    osg::ref_ptr<osg::Group> getroot(){
        return root;
    }

    virtual void keyPressEvent(QKeyEvent* event);
    virtual void keyReleaseEvent(QKeyEvent* event);
    virtual void mousePressEvent(QMouseEvent* event);
    virtual void mouseReleaseEvent(QMouseEvent* event);

    virtual void mouseDoubleClickEvent(QMouseEvent* event);
    virtual void mouseMoveEvent(QMouseEvent* event);
    virtual void wheelEvent(QWheelEvent* event);

    virtual void resize(int windowWidth, int windowHeight, float windowScale);

    void setupOSG(int windowWidth, int windowHeight, float windowScale);
    void redarw();
    // overrided from osgViewer::Viewer
    virtual bool checkNeedToDoFrame() override;

    // overrided from osgViewer::ViewerBase
    void frame(double simulationTime = USE_REFERENCE_TIME) override;
    // overrided from osgViewer::Viewer
    void requestRedraw() override;
    // overrided from osgViewer::Viewer
    bool checkEvents() override;
    void update();
    void addModel(osg::MatrixTransform* mtx, osg::Node *node);
    void showground(bool isshow);//显示地板
    void showobject(bool isshow,osg::ref_ptr<osg::Node> node);
    void showgGrid(bool isshow);//显示地板
    void setGridSize(double width,double height);

private:
    void createAxis(osg::Transform* previousJoint);//创建坐标系
    void scale(osg::MatrixTransform* mtx,float tarscale);
    void rotation(osg::MatrixTransform* mtx,double angle,osg::Vec3d dir);
    void translate(osg::MatrixTransform* mtx,osg::Vec3d trans);
    osg::Camera* createHudCamera(osgViewer::Viewer* viewer,int width=1024,int height=1024);

protected:
    void timerEvent(QTimerEvent* event) override;
    void setKeyboardModifiers(QInputEvent* event);
    osg::Node* createBase(const osg::Vec3d& center,float radius);
    osg::Node* createGrid(double wd, double ht);
private:
    osg::ref_ptr<osg::Node> floor;
    osg::ref_ptr<osg::Node> grid;
    double gridwidth;
    double gridheight;
};

class osgQOpenGLWidget : public QOpenGLWidget,protected QOpenGLFunctions
{
    Q_OBJECT

protected:
    OSGRenderer* m_renderer {nullptr};
    bool _osgWantsToRenderFrame{true};
    OpenThreads::ReadWriteMutex _osgMutex;
    osg::ArgumentParser* _arguments {nullptr};
    bool _isFirstFrame {true};

    friend class OSGRenderer;

public:
    osgQOpenGLWidget(QWidget* parent = nullptr);
    osgQOpenGLWidget(osg::ArgumentParser* arguments, QWidget* parent = nullptr);
    virtual ~osgQOpenGLWidget();

    /** Get osgViewer View */
    virtual osgViewer::Viewer* getOsgViewer();

    //! get mutex
    virtual OpenThreads::ReadWriteMutex* mutex();

    //! override this to change default size or aspect ratio
    QSize sizeHint() const override { return QSize(640,480); }

    void showfloor(bool isshow);
    void Display(osg::ref_ptr<osg::Node> node);
    void showobject(bool isshow,osg::ref_ptr<osg::Node> node);




signals:
    void initialized();

protected:

    //! call createRender. If overloaded, this method must send initialized signal at end
    void initializeGL() override;

    void resizeGL(int w, int h) override;

    //! lock scene graph and call osgViewer::frame()
    void paintGL() override;

    //! called before creating renderer
    virtual void setDefaultDisplaySettings();

    void keyPressEvent(QKeyEvent* event) override;
    void keyReleaseEvent(QKeyEvent* event) override;
    void mousePressEvent(QMouseEvent* event) override;
    void mouseReleaseEvent(QMouseEvent* event) override;
    void mouseDoubleClickEvent(QMouseEvent* event) override;
    void mouseMoveEvent(QMouseEvent* event) override;
    void wheelEvent(QWheelEvent* event) override;

    void createRenderer();
    void scale(osg::MatrixTransform* mtx,float tarscale);
    void rotation(osg::MatrixTransform* mtx,double angle,osg::Vec3d dir);
    void translate(osg::MatrixTransform* mtx,osg::Vec3d trans);

private:
    QList<osg::ref_ptr<osg::Node> > _containt;

};


#endif // OSGQT_H
